﻿using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace Vulcano.Helpers.ptBRParser
{
    public class NextNYears :DateTimeParserBase,IDateTimeParser
    {
        
        public Regex Regex()
        {
            return new Regex(@"pr(ó|o)ximos +([2-9]\d*) +anos");
        }
        
        public DateTime Parse(Match m)
        {
            var val = int.Parse(m.Groups[2].Value);
            return today.AddYears(val);
        }
    }

    public class NextNWeeks : DateTimeParserBase, IDateTimeParser
    {

        public Regex Regex()
        {
            return new Regex(@"pr(ó|o)ximas +([2-9]\d*) +semanas");
        }

        public DateTime Parse(Match m)
        {
            var val = int.Parse(m.Groups[2].Value);
            return today.AddDays(val * 7);
        }
    }

    public class NextNMonths : DateTimeParserBase, IDateTimeParser
    {

        public Regex Regex()
        {
            return new Regex(@"pr(ó|o)ximos +([2-9]\d*) +m(ê|e)ses");
        }

        public DateTime Parse(Match m)
        {
            var val = int.Parse(m.Groups[2].Value);
            return today.AddMonths(val);
        }
    }
    
    public class NextNDays : DateTimeParserBase, IDateTimeParser
    {

        public Regex Regex()
        {
            return new Regex(@"pr(ó|o)ximos +([2-9]\d*) +dias");
        }

        public DateTime Parse(Match m)
        {
            var val = int.Parse(m.Groups[2].Value);
            return today.AddDays(val);
        }
    }

    public class NextWeekDay : DateTimeParserBase, IDateTimeParser
    {
        List<string> dayList = new List<string>() { "dom", "seg", "ter", "qua", "qui", "sex", "sab","sáb" };

        public Regex Regex()
        {
            return new Regex(String.Format(@"((ú|u)ltim(o|a)|pr(ó|o)xim(o|a)) *({0}).*", String.Join("|", dayList.ToArray())));
        }

        public DateTime Parse(Match m)
        {
            var val = m.Groups[6].Value;
            var direction = (m.Groups[1].Value.StartsWith("últim") || m.Groups[1].Value.StartsWith("ultim")) ? -1 : 1;
            var dayOfWeek = dayList.IndexOf(val.Substring(0, 3));

            if (dayOfWeek == 7)
                dayOfWeek--;

            if (dayOfWeek >= 0)
            {
                var diff = direction * (dayOfWeek - (int)DateTime.Today.DayOfWeek);
                if (diff <= 0)
                {
                    diff = 7 + diff;
                }
                return DateTime.Today.AddDays(direction * diff);
            }
            return DateTime.MinValue;
        }
    }

    public class Now : DateTimeParserBase, IDateTimeParser
    {

        public Regex Regex()
        {
            return new Regex(@"agora");
        }

        public DateTime Parse(Match m)
        {
            return DateTime.Now;
        }
    }

    public class Tomorrow : DateTimeParserBase, IDateTimeParser
    {

        public Regex Regex()
        {
            return new Regex(@"amanh(ã|a)");
        }

        public DateTime Parse(Match m)
        {
            return today.AddDays(1);
        }
    }

    public class Yesterday : DateTimeParserBase, IDateTimeParser
    {

        public Regex Regex()
        {
            return new Regex(@"ontem");
        }

        public DateTime Parse(Match m)
        {
            return today.AddDays(-1);
        }
    }

    public class Today : DateTimeParserBase, IDateTimeParser
    {

        public Regex Regex()
        {
            return new Regex(@"hoje");
        }

        public DateTime Parse(Match m)
        {
            return today;
        }
    }

    public class NextLastWeekMonthYear : DateTimeParserBase, IDateTimeParser
    {

        public Regex Regex()
        {
            return new Regex(@"((u|ú)ltim(a|o)|pr(o|ó)xim(a|o)) *(semana|ano|m(e|ê)s)");
        }

        public DateTime Parse(Match m)
        {
            int direction = (m.Groups[1].Value.Contains("ltim") ? -1 : 1);
            switch (m.Groups[6].Value)
            {
                case "semana":
                    return today.AddDays(7 * direction);
                case "ano":
                    return today.AddYears(direction);
                case "mes":
                case "mês":
                case "meses":
                case "mêses":
                    return today.AddMonths(direction);
            }
            return DateTime.MinValue;
        }
    }

    public class WeekMonthYearNextLast : DateTimeParserBase, IDateTimeParser
    {

        public Regex Regex()
        {
            return new Regex(@"(semana|ano|m(e|ê)s) *(que vem|passad(o|a))");
        }

        public DateTime Parse(Match m)
        {
            int direction = (m.Groups[3].Value.Contains("passad") ? -1 : 1);
            switch (m.Groups[1].Value)
            {
                case "semana":
                    return today.AddDays(7 * direction);
                case "ano":
                    return today.AddYears(direction);
                case "mes":
                case "mês":
                case "meses":
                case "mêses":
                    return today.AddMonths(direction);
            }
            return DateTime.MinValue;
        }
    }

    public class NSecondsMinutesHoursDaysWeeksMonthsYearsAgo : DateTimeParserBase, IDateTimeParser
    {

        public Regex Regex()
        {
            return new Regex(@"([1-9]\d*) *(segundo(s)?|minuto(s)?|hora(s)?|dia(s)?|semana(s)?|m(e|ê)(s|ses)?|ano(s)?) +atr(a|á)s");
        }

        public DateTime Parse(Match m)
        {
            var val = int.Parse(m.Groups[1].Value);
            switch (m.Groups[2].Value)
            {
                case "segundo":
                case "segundos":
                    return DateTime.Now.AddSeconds(-val);
                case "minuto":
                case "minutos":
                    return DateTime.Now.AddMinutes(-val);
                case "hora":
                case "horas":
                    return DateTime.Now.AddHours(-val);
                case "dia":
                case "dias":
                    return today.AddDays(-val);
                case "semana":
                case "semanas":
                    return today.AddDays(-val*7);
                case "mes":
                case "mês":
                case "meses":
                case "mêses":
                    return today.AddMonths(-val);
                case "ano":
                case "anos":
                    return today.AddYears(-val);
            }
            return DateTime.MinValue;

        }

    }

    public class InNSecondsMinutesHoursDaysWeeksMonthsYears : DateTimeParserBase, IDateTimeParser
    {

        public Regex Regex()
        {
            return new Regex(@"(daqui a|em) ([1-9]\d*) *(segundo(s)?|minuto(s)?|hora(s)?|dia(s)?|semana(s)?|m(e|ê)(s|ses)?|ano(s)?)");
        }

        public DateTime Parse(Match m)
        {
            var val = int.Parse(m.Groups[2].Value);
            switch (m.Groups[3].Value)
            {
                case "segundo":
                case "segundos":
                    return DateTime.Now.AddSeconds(val);
                case "minuto":
                case "minutos":
                    return DateTime.Now.AddMinutes(val);
                case "hora":
                case "horas":
                    return DateTime.Now.AddHours(val);
                case "dia":
                case "dias":
                    return today.AddDays(val);
                case "semana":
                case "semanas":
                    return today.AddDays(val * 7);
                case "mes":
                case "mês":
                case "meses":
                case "mêses":
                    return today.AddMonths(val);
                case "ano":
                case "anos":
                    return today.AddYears(val);
            }
            return DateTime.MinValue;

        }

    }     
    
}
